﻿
#region Using

using GalaSoft.MvvmLight.Command;
using Rio.Manager.Application.ViewModel.BaseClass;
using Rio.Framework.Localisation;
using System;
using System.Collections.ObjectModel;
using System.ServiceModel.DomainServices.Client;
using NetBay.Core.BusinessEntities.ActiveDirectory;
using System.Linq;
using Rio.Framework.Pages;
using System.Collections.Generic;
using Rio.Applications.Web.Services.AD;
using NetBay.Core.Silverlight.Log;

#endregion Using

namespace Rio.Manager.Application.ViewModel.Administration
{
    public class GroupSynchronizationTabViewModel : TabViewModelBase
    {
        #region Fields

        private AdDomainContext _oAdDomainContext;

        public RelayCommand InitializationCommand { get; set; }
        public RelayCommand SaveCorrespondenceRioAdCommand { get; set; }
        public RelayCommand CloseCorrespondenceRioAdCommand { get; set; }

        private string _LblRioAndAdAssociationExplanation;

        private string _LblConfiAd;

        private string _LblLogin;

        private string _LblFirstName;

        private string _LblLastName;

        private string _LblMail;

        private ObservableCollection<AdStructureItem> _AdConfigCustomer;

        private AdStructureItem _SelectedAdConfigCustomer;

        private ObservableCollection<AdInformationUserRio> _RioAndADCorrespondenceInRioDatabase;

        private ObservableCollection<string> _ColumnValueAD;

        private Boolean _EnabledColumnAdAndBtnSave;

        private string _SelectedDisplayADColumnLogin;

        private string _SelectedDisplayADColumnLastName;

        private string _SelectedDisplayADColumnFirstName;

        private string _SelectedDisplayADColumnMail;

        private string _BtnSave;

        private string _BtnClose;
        
        #endregion Fields

        #region Properties

        public AdDomainContext GetAdContext
        {
            get { return _oAdDomainContext ?? (_oAdDomainContext = new AdDomainContext()); }
        }

        public string LblRioAndAdAssociationExplanation
        {
            get
            {
                return _LblRioAndAdAssociationExplanation;
            }
            set
            {
                _LblRioAndAdAssociationExplanation = value;
                RaisePropertyChanged("LblRioAndAdAssociationExplanation");
            }
        }

        public string LblConfiAd
        {
            get
            {
                return _LblConfiAd;
            }
            set
            {
                _LblConfiAd = value;
                RaisePropertyChanged("LblConfiAd");
            }
        }

        public string LblLogin
        {
            get
            {
                return _LblLogin;
            }
            set
            {
                _LblLogin = value;
                RaisePropertyChanged("LblLogin");
            }
        }

        public string LblFirstName
        {
            get
            {
                return _LblFirstName;
            }
            set
            {
                _LblFirstName = value;
                RaisePropertyChanged("LblFirstName");
            }
        }

        public string LblLastName
        {
            get
            {
                return _LblLastName;
            }
            set
            {
                _LblLastName = value;
                RaisePropertyChanged("LblLastName");
            }
        }

        public string LblMail
        {
            get
            {
                return _LblMail;
            }
            set
            {
                _LblMail = value;
                RaisePropertyChanged("LblMail");
            }
        }

        public ObservableCollection<AdStructureItem> AdConfigCustomer
        {
            get
            {
                return _AdConfigCustomer;
            }
            set
            {
                _AdConfigCustomer = value;
                RaisePropertyChanged("AdConfigCustomer");
            }
        }

        public AdStructureItem SelectedAdConfigCustomer
        {
            get
            {
                return _SelectedAdConfigCustomer;
            }
            set
            {
                _SelectedAdConfigCustomer = value;
                RaisePropertyChanged("SelectedAdConfigCustomer");

                //Fill Ad configuration column. 
                if (SelectedAdConfigCustomer.AdName != null)
                {
                    InitProperties(false);
                    FillCustomerADColumn();
                }
            }
        }

        public ObservableCollection<AdInformationUserRio> RioAndADCorrespondenceInRioDatabase
        {
            get
            {
                return _RioAndADCorrespondenceInRioDatabase;
            }
            set
            {
                _RioAndADCorrespondenceInRioDatabase = value;
                RaisePropertyChanged("RioAndADCorrespondenceInRioDatabase");
            }
        }

        public ObservableCollection<String> ColumnValueAD
        {
            get
            {
                return _ColumnValueAD;
            }
            set
            {
                _ColumnValueAD = value;
                RaisePropertyChanged("ColumnValueAD");
            }
        }

        public Boolean EnabledColumnAdAndBtnSave
        {
            get
            {
                return _EnabledColumnAdAndBtnSave;
            }
            set
            {
                _EnabledColumnAdAndBtnSave = value;
                RaisePropertyChanged("EnabledColumnAdAndBtnSave");
            }
        }

        public string SelectedDisplayADColumnLogin
        {
            get
            {
                return _SelectedDisplayADColumnLogin;
            }
            set
            {
                _SelectedDisplayADColumnLogin = value;
                RaisePropertyChanged("SelectedDisplayADColumnLogin");
            }
        }

        public string SelectedDisplayADColumnLastName
        {
            get
            {
                return _SelectedDisplayADColumnLastName;
            }
            set
            {
                _SelectedDisplayADColumnLastName = value;
                RaisePropertyChanged("SelectedDisplayADColumnLastName");
            }
        }

        public string SelectedDisplayADColumnFirstName
        {
            get
            {
                return _SelectedDisplayADColumnFirstName;
            }
            set
            {
                _SelectedDisplayADColumnFirstName = value;
                RaisePropertyChanged("SelectedDisplayADColumnFirstName");
            }
        }

        public string SelectedDisplayADColumnMail
        {
            get
            {
                return _SelectedDisplayADColumnMail;
            }
            set
            {
                _SelectedDisplayADColumnMail = value;
                RaisePropertyChanged("SelectedDisplayADColumnMail");
            }
        }

        public string BtnSave
        {
            get
            {
                return _BtnSave;
            }
            set
            {
                _BtnSave = value;
                RaisePropertyChanged("BtnSave");
            }
        }

        public string BtnClose
        {
            get
            {
                return _BtnClose;
            }
            set
            {
                _BtnClose = value;
                RaisePropertyChanged("BtnClose");
            }
        }

        #endregion Properties

        #region Constructor and Initialization

        public GroupSynchronizationTabViewModel()
            : base()
        {
            CanCloseTab = true;

            //Icon.
            TabIcon = new Uri("/Rio.Manager.Application;component/Assets/Images/User_Information With_AD.png", UriKind.Relative);    
        }

        /// <summary>Inits the commands.</summary>
        public override void InitCommands()
        {
            InitializationCommand = new RelayCommand(Initialization);
            SaveCorrespondenceRioAdCommand = new RelayCommand(SaveRioAndADCorrespondence);
            CloseCorrespondenceRioAdCommand = new RelayCommand(CloseRioAndADCorrespondence);
        }

        /// <summary>Initializations this instance.</summary>
        private void Initialization()
        {
            InitLabels();
            InitProperties(true);
            FillADConfigurationAndCorrespondenceSaved();
        }

        /// <summary>Inits the labels.</summary>
        public override void InitLabels()
        {
            //Retrieves the labels. 
            TabTitle = Resx.GetLabel(ResxRioManagerGroup.GROUP_CORRESPONDENCE);
            LblLogin = Resx.GetLabel(ResxRioManagerGroup.GROUP_CORRESPONDENCE_LOGIN);
            LblLastName = Resx.GetLabel(ResxRioManagerGroup.GROUP_CORRESPONDENCE_LASTNAME);
            LblFirstName = Resx.GetLabel(ResxRioManagerGroup.GROUP_CORRESPONDENCE_FIRSTNAME);            
            LblMail = Resx.GetLabel(ResxRioManagerGroup.GROUP_CORRESPONDENCE_MAIL);
            LblRioAndAdAssociationExplanation = Resx.GetLabel(ResxRioManagerGroup.GROUP_CORRESPONDENCE_EXPLANATION);
            LblConfiAd = Resx.GetLabel(ResxRioManagerGroup.GROUP_AD_CONFIG);  
            BtnClose = Resx.GetLabel(ResxRioManagerGroup.GROUP_CORRESPONDENCE_BTN_CLOSE);
            BtnSave = Resx.GetLabel(ResxRioManagerGroup.GROUP_CORRESPONDENCE_BTN_SAVE);
        }

        /// <summary>Inits the properties.</summary>
        public void InitProperties(Boolean p_bInitAll)
        {
            //Initialize properties.
            if (p_bInitAll)
            {
                SelectedAdConfigCustomer = new AdStructureItem();
            }
            SelectedDisplayADColumnFirstName = string.Empty;
            SelectedDisplayADColumnLastName = string.Empty;
            SelectedDisplayADColumnLogin = string.Empty;
            SelectedDisplayADColumnMail = string.Empty;
            EnabledColumnAdAndBtnSave = false;
            ColumnValueAD = new ObservableCollection<string>();
        }

        /// <summary>Fill Ad Configuration and correspondence saved in the database.</summary>
        public void FillADConfigurationAndCorrespondenceSaved()
        {
            //Load all customer configuration Ad.
            var query = GetAdContext.GetAdConfigListQuery();
            GetAdContext.Load(query, OnGetAdConfigListQueryCallback, null);
        }

        /// <summary>Inits the Rio database information.</summary>
        public void InitRioCorrespondenceDatabase()
        {
            //Retrieves the customer information AD Column in Rio Database.
            var query = GetAdContext.GetAllRioADCorrespondenceQuery();
            GetAdContext.Load(query, OnGetAllRioAndADCorrespondenceCallback, null);
        }
        
        #endregion Constructor and Initialization

        #region Methods

        /// <summary>
        /// Fill the customer Ad Column.
        /// </summary>
        public void FillCustomerADColumn(ObservableCollection<AdInformationUserRio> p_oRioAndADCorrespondenceList = null)
        {
            //Log.
            string l_sLogMsg = p_oRioAndADCorrespondenceList == null ? 
                            "GroupSynchronizationTabViewModel.FillCustomerADColumn (p_oRioAndADCorrespondenceList is null)..." :
                            "GroupSynchronizationTabViewModel.FillCustomerADColumn (p_oRioAndADCorrespondenceList.Count <" + p_oRioAndADCorrespondenceList.Count + ">)...";
            Logger.Write(l_sLogMsg, Logger.Level.Debug);
            
            //Busy indicator.
            BusyIndicator.Clear();
            BusyIndicator.AddBusyTask();

            //Load all customer configuration Ad columns.
            GetAdContext.GetAdUserColumnStructure(SelectedAdConfigCustomer, result =>
            {
                if (result.HasError)
                {
                    //Log Error.
                    Logger.Write("GroupSynchronizationTabViewModel.GetAdUserColumnStructure Exception [" + result.Error.Message + "]", Logger.Level.Error);

                    //User error message.
                    MessageBoxChildWindow L_oMessage = new MessageBoxChildWindow(String.Empty, Resx.GetLabel(ResxRioManagerGroup.GROUP_MSG_CORRESPONDENCE_AD_CONFIG_COLUMN_ERROR), MessageBoxButtons.Ok, MessageBoxIcon.Error);
                    L_oMessage.Show();
                }
                else
                {
                    //Set Ad Column name.
                    OnGetAdUserColumnStructureCallback((result.Value).ToList(), p_oRioAndADCorrespondenceList);
                }

                //Busy indicator.
                BusyIndicator.RemoveBusyTask();

            },
                null);    
        }

        /// <summary>
        /// Differents test befor saving.
        /// </summary>
        public Boolean TestBeforSaveAndUpdate()
        {
            //Varible initilization.
            Boolean l_bReturnResult = true;
            string l_sMessage = string.Empty;
            List<string> l_oListEmptyInformation = new List<string>();

            //Log.
            Logger.Write("GroupSynchronizationTabViewModel.TestBeforSaveAndUpdate (No parameters)...", Logger.Level.Debug);

            //Test information completed.
            if (string.IsNullOrEmpty(SelectedDisplayADColumnLastName))
            {
                l_oListEmptyInformation.Add(LblLastName);
            }
            if (string.IsNullOrEmpty(SelectedDisplayADColumnFirstName))
            {
                l_oListEmptyInformation.Add(LblFirstName);
            }
            if (string.IsNullOrEmpty(SelectedDisplayADColumnLogin))
            {
                l_oListEmptyInformation.Add(LblLogin);
            }
            if (string.IsNullOrEmpty(SelectedDisplayADColumnMail))
            {
                l_oListEmptyInformation.Add(LblMail);
            }

            //Test is correct or bad.
            if (l_oListEmptyInformation.Count != 0)
            {
                //Return value.
                l_bReturnResult = false;

                //User message.
                if (l_oListEmptyInformation.Count == 1)
                {
                    MessageBoxChildWindow L_oMessage = new MessageBoxChildWindow(String.Empty, string.Format(Resx.GetLabel(ResxRioManagerGroup.GROUP_MSG_CORRESPONDENCE_AD_RIO_MANDATORY_INFORMATION), l_oListEmptyInformation[0]), MessageBoxButtons.Ok, MessageBoxIcon.Error);
                    L_oMessage.Show();
                    L_oMessage.Closed += (s, ev) =>
                    {
                        l_bReturnResult = false;
                    };
                }
                else
                {
                    //Build message.
                    l_sMessage = string.Format("{0}'", l_sMessage);
                    l_sMessage = l_oListEmptyInformation.Aggregate(l_sMessage, (current, l_sEmptyElement) => current + string.Format("{0}', '", l_sEmptyElement));

                    //Format message.
                    l_sMessage = l_sMessage.Substring(0, l_sMessage.Length - 3);
                    l_sMessage = string.Format("{0} {1} {2}", l_sMessage.Substring(0, l_sMessage.LastIndexOf(",")), Resx.GetLabel(ResxCommon.AND), l_sMessage.Substring(l_sMessage.LastIndexOf(",") + 1, l_sMessage.Length - l_sMessage.LastIndexOf(",") - 1));

                    //User message.
                    MessageBoxChildWindow L_oMessage = new MessageBoxChildWindow(String.Empty, string.Format(Resx.GetLabel(ResxRioManagerGroup.GROUP_MSG_CORRESPONDENCE_AD_RIO_MANDATORY_INFORMATIONS), l_oListEmptyInformation.Count, l_sMessage), MessageBoxButtons.Ok, MessageBoxIcon.Error);
                    L_oMessage.Show();
                    L_oMessage.Closed += (s, ev) =>
                    {
                        l_bReturnResult = false;
                    };
                }
            }

            //Return value.
            return l_bReturnResult;
        }

        /// <summary>
        /// Save or update Rio and AD correspondence.
        /// </summary>
        public void SaveUpdateRioAndADCorrespondence()
        {
            //Log.
            Logger.Write("GroupSynchronizationTabViewModel.SaveUpdateRioAndADCorrespondence (No parameters)...", Logger.Level.Debug);

            try
            {
                //Variable initialization.
                AdInformationUserRio l_oAdInformationUserRio;

                //LastName build.
                l_oAdInformationUserRio = GetAdContext.AdInformationUserRios.Where(p => p.Type == UserRioInformationType.LastName).FirstOrDefault();
                l_oAdInformationUserRio.Value = SelectedDisplayADColumnLastName;
                l_oAdInformationUserRio.AdName = SelectedAdConfigCustomer.AdName;
                
                //FirstName build.
                l_oAdInformationUserRio = GetAdContext.AdInformationUserRios.Where(p => p.Type == UserRioInformationType.FirstName).FirstOrDefault();
                l_oAdInformationUserRio.Value = SelectedDisplayADColumnFirstName;
                l_oAdInformationUserRio.AdName = SelectedAdConfigCustomer.AdName;

                //Login build.
                l_oAdInformationUserRio = GetAdContext.AdInformationUserRios.Where(p => p.Type == UserRioInformationType.Login).FirstOrDefault();
                l_oAdInformationUserRio.Value = SelectedDisplayADColumnLogin;
                l_oAdInformationUserRio.AdName = SelectedAdConfigCustomer.AdName;

                //Mail build.
                l_oAdInformationUserRio = GetAdContext.AdInformationUserRios.Where(p => p.Type == UserRioInformationType.Email).FirstOrDefault();
                l_oAdInformationUserRio.Value = SelectedDisplayADColumnMail;
                l_oAdInformationUserRio.AdName = SelectedAdConfigCustomer.AdName;

                //Save informations.
                GetAdContext.SubmitChanges(OnSubmitChangeCallback, null);
            }
            catch (Exception ex)
            {
                //Log error.
                Logger.Write("GroupSynchronizationTabViewModel.SaveUpdateRioAndADCorrespondence Exception [" + ex.Message + "]", Logger.Level.Error);

                //User error message.
                MessageBoxChildWindow L_oMessage = new MessageBoxChildWindow(String.Empty, Resx.GetLabel(ResxRioManagerGroup.GROUP_MSG_CORRESPONDENCE_UPDATE_ERROR), MessageBoxButtons.Ok, MessageBoxIcon.Error);
                L_oMessage.Show();
            }
        }

        #endregion Methods

        #region Button Click (command)

        /// <summary>
        /// Close the correspondence Rio and AD tab.
        /// </summary>
        public void CloseRioAndADCorrespondence()
        {
            //Close the correspondence Rio and AD tab.
            CloseTab();
        }

        /// <summary>
        /// Save the correspondence Rio and AD tab.
        /// </summary>
        public void SaveRioAndADCorrespondence()
        {
            //Save or Update the correspondence Rio and AD tab.
            if (TestBeforSaveAndUpdate())
            {
                SaveUpdateRioAndADCorrespondence();
            }
        }

        #endregion Button Click (command)

        #region Callback

        /// <summary>
        /// GetAdConfigListQuery Callback
        /// </summary>
        /// <param name="result">The result.</param>
        public void OnGetAdConfigListQueryCallback(LoadOperation<AdConfig> result)
        {
            //Variable initialization.
            MessageBoxChildWindow L_oMessage;

            //All Ad config.
            if (result.HasError)
            {
                //Log error.
                Logger.Write("GroupSynchronizationTabViewModel.OnGetAdConfigListQueryCallback Exception [" + result.Error.Message + "]", Logger.Level.Error);

                //User error message.
                L_oMessage = new MessageBoxChildWindow(String.Empty, Resx.GetLabel(ResxRioManagerGroup.GROUP_MSG_CORRESPONDENCE_AD_CONFIG_ERROR), MessageBoxButtons.Ok, MessageBoxIcon.Error);
                L_oMessage.Show();
            }
            else
            {
                //Built the AdConfig list.
                List<AdConfig> l_oAdConfig = new List<AdConfig>(result.Entities);

                if (l_oAdConfig[0].LstAdStructureItem.Count != 0)
                {
                    //Fill all AD configuration.
                    AdConfigCustomer = new ObservableCollection<AdStructureItem>();
                    foreach (AdStructureItem l_oAdStructureItem in l_oAdConfig[0].LstAdStructureItem)
                    {
                        AdConfigCustomer.Add(l_oAdStructureItem);
                    }

                    //Retrieves information saved.
                    InitRioCorrespondenceDatabase();
                }
                else
                {
                    //User message not configuration in the web.config.
                    L_oMessage = new MessageBoxChildWindow(String.Empty, Resx.GetLabel(ResxRioManagerGroup.GROUP_MSG_CORRESPONDENCE_AD_NOT_CONFIG), MessageBoxButtons.Ok, MessageBoxIcon.Warning);
                    L_oMessage.Show();
                }
            }
        }

        /// <summary>Gets all Rio and AD Correspondence.</summary>
        /// <param name="result">Rio and AD Correspondence List.</param>
        private void OnGetAllRioAndADCorrespondenceCallback(LoadOperation<AdInformationUserRio> result)
        {
            if (!result.HasError)
            {
                //Built Rio and AD Correspondence list.
                ObservableCollection<AdInformationUserRio> l_oRioAndADCorrespondenceList = new ObservableCollection<AdInformationUserRio>(result.Entities);

                if ((l_oRioAndADCorrespondenceList.Count != 0) && (AdConfigCustomer != null))
                {
                    //Set the SelectedAdConfigCustomer property.
                    foreach (AdStructureItem l_oAdStructureItem in AdConfigCustomer)
                    {
                        //Test if Ad name database is in the config file.
                        if (l_oAdStructureItem.AdName != l_oRioAndADCorrespondenceList[0].AdName) continue;

                        //Ad config selected. 
                        SelectedAdConfigCustomer = l_oAdStructureItem;

                        //Save button title.
                        BtnSave = Resx.GetLabel(ResxRioManagerGroup.GROUP_CORRESPONDENCE_BTN_UPDATE);

                        //Fill Rio information and Ad column save in the database.
                        FillCustomerADColumn(l_oRioAndADCorrespondenceList);

                        break;
                    }

                    if (SelectedAdConfigCustomer.AdName == null)
                    {
                        //User message not configuration in the web.config in correspondence with database information saved.
                        MessageBoxChildWindow L_oMessage = new MessageBoxChildWindow(Resx.GetLabel(ResxCommon.INFORMATION), string.Format(Resx.GetLabel(ResxRioManagerGroup.GROUP_MSG_CORRESPONDENCE_AD_NAME_HAS_CHANGE).Replace("\\n", Environment.NewLine), l_oRioAndADCorrespondenceList[0].AdName), MessageBoxButtons.Ok, MessageBoxIcon.Warning);
                        L_oMessage.Show();
                    }
                }
            }
            else
            {
                //Log Error.
                Logger.Write("GroupSynchronizationTabViewModel.OnGetAllRioAndADCorrespondence Exception [" + result.Error.Message + "]", Logger.Level.Error);
            }
        }

        /// <summary>Gets the customer column ad name.</summary>
        /// <param name="p_listAdColumnName"></param>
        /// <param name="p_oRioAndADCorrespondenceList"></param>
        private void OnGetAdUserColumnStructureCallback(List<string> p_listAdColumnName, ObservableCollection<AdInformationUserRio> p_oRioAndADCorrespondenceList)
        {
            //Set Ad Column name sorted --> sort an List of string for to add Observablecollection of string sorted.
            p_listAdColumnName.Sort();
            List<string> l_sLstADColumnNameSorted = p_listAdColumnName;
            foreach (string l_sADColumnNameItemSorted in l_sLstADColumnNameSorted)
            {
                ColumnValueAD.Add(l_sADColumnNameItemSorted);
            }

            //Selected value database.
            if (p_oRioAndADCorrespondenceList != null)
            {
                foreach (AdInformationUserRio l_oOneRioADCorrespondence in p_oRioAndADCorrespondenceList)
                {
                    //Test on the column name Ad and database value.
                    if (!ColumnValueAD.Any(f => f.Contains(l_oOneRioADCorrespondence.Value))) continue;

                    switch (l_oOneRioADCorrespondence.Type)
                    {
                        case UserRioInformationType.LastName:
                            SelectedDisplayADColumnLastName = l_oOneRioADCorrespondence.Value;
                            break;
                        case UserRioInformationType.FirstName:
                            SelectedDisplayADColumnFirstName = l_oOneRioADCorrespondence.Value;
                            break;
                        case UserRioInformationType.Login:
                            SelectedDisplayADColumnLogin = l_oOneRioADCorrespondence.Value;
                            break;
                        case UserRioInformationType.Email:
                            SelectedDisplayADColumnMail = l_oOneRioADCorrespondence.Value;
                            break;
                    }
                }
            }

            //Ad column is fill --> Selectable.
            EnabledColumnAdAndBtnSave = true;
        }
        
        /// <summary>Save or Update Rio and Ad Correspondences.</summary>
        /// <param name="e"></param>
        private void OnSubmitChangeCallback(SubmitOperation e)
        {
            if (e.HasError)
            {
                //Log error.
                Logger.Write("GroupSynchronizationTabViewModel.OnSubmitChangeCallback Exception [" + e.Error.Message + "]", Logger.Level.Error);

                //User error message.
                MessageBoxChildWindow L_oMessage = new MessageBoxChildWindow(String.Empty, Resx.GetLabel(ResxRioManagerGroup.GROUP_MSG_CORRESPONDENCE_UPDATE_ERROR), MessageBoxButtons.Ok, MessageBoxIcon.Error);
                L_oMessage.Show();
                e.MarkErrorAsHandled();
            }
            else
            {
                //User sucessfull message.
                MessageBoxChildWindow L_oMessage = new MessageBoxChildWindow(String.Empty, Resx.GetLabel(ResxRioManagerGroup.GROUP_MSG_CORRESPONDENCE_UPDATE_SUCCES), MessageBoxButtons.Ok, MessageBoxIcon.Information);
                L_oMessage.Show();
                L_oMessage.Closed += (s, ev) => CloseTab();
            }
        }

        #endregion Callback
    }
}
